<html>
    <head>
        <title>使用自己的数据库表创建新的实体</title>
    </head>
    <body>
        <script>
             /*
                        四、使用自己的数据库表/集合创建新实体

                                将你的实体映射到依赖模块的现有表有一些缺点：

                                    ①、你处理EF Core的数据库迁移结构。虽然可能，但你应该格外注意迁移代码，尤其是当你想在实体之间添加关系时。

                                    ②、你的应用程序数据库和模块数据库将是相同的物理数据库。通常，如果需要，可以将模块数据库分开，但使用相同的表会限制它。


                                如果你想将你的实体与模块定义的实体松散耦合，你可以创建自己的数据库表/集合并将你的实体映射到你自己的数据库中自己的表。

                                在这种情况下，你需要处理同步问题，特别是如果你想复制相关实体的一些属性/字段。有几个解决方案：

                                    ①、如果你正在构建一个单体应用程序（或在同一进程中管理你的实体和相关模块实体），你可以使用本地事件总线来侦听更改。

                                    ②、如果你正在构建一个分布式系统，其中模块实体在与你的实体管理不同的进程/服务上进行管理（创建/更新/删除），
                                    
                                            那么你可以订阅分布式事件总线以获取更改事件。

                                处理事件后，你可以在自己的数据库中更新自己的实体。


                                1、使用本地事件总线

                                          本地事件总线系统是一种发布和订阅同一应用程序中发生的事件的方式
                                          
                                          假设你希望在IdentityUser实体更改（创建、更新或删除）时获得通知。
                                          
                                          你可以创建一个实现ILocalEventHandler<EntityChangedEventData<IdentityUser>>接口的类：

                                                public class MyLocalIdentityUserChangeEventHandler :
                                                    ILocalEventHandler<EntityChangedEventData<IdentityUser>>,
                                                    ITransientDependency
                                                {
                                                    public async Task HandleEventAsync(EntityChangedEventData<IdentityUser> eventData)
                                                    {
                                                        var userId = eventData.Entity.Id;
                                                        var userName = eventData.Entity.UserName; 
                                                        
                                                        //...
                                                    }
                                                }

                                          EntityChangedEventData<T>涵盖了给定实体的创建、更新和删除事件。如果需要，你可以单独订阅创建、更新和删除事件（在同一类或不同类中）。

                                          这段代码将在当前工作单元中执行，整个过程变成事务性的。
                                
                                2、使用分布式事件总线

                                          分布式事件总线系统是一种在一个应用程序中发布事件并在运行在相同或不同服务器上的相同或不同应用程序中接收事件的方式。

                                          假设你希望在Tenant实体（属于租户管理模块）创建时获得通知。
                                          
                                          在这种情况下，你可以订阅EntityCreatedEto<TenantEto>事件，如以下示例所示：
                                         
                                                public class MyDistributedEventHandler :
                                                    IDistributedEventHandler<EntityCreatedEto<TenantEto>>,
                                                    ITransientDependency
                                                {
                                                    public async Task HandleEventAsync(EntityCreatedEto<TenantEto> eventData)
                                                    {
                                                        var tenantId = eventData.Entity.Id;
                                                        var tenantName = eventData.Entity.Name;
                                                        //...your custom logic
                                                    }

                                                    //...
                                                }

                                          此处理程序仅在创建新租户时执行。所有预构建的ABP应用程序模块都为其实体定义了相应的ETO类型。因此，你可以在它们更改时轻松获得通知。


                    */
        </script>
    </body>
</html>